{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PS Clock Control\n",
    "This notebook demonstrates how to use `Clocks` class to control the PL clocks.\n",
    "\n",
    "By default, there are at most 4 PL clocks enabled in the system. They all can be reprogrammed to valid clock rates.\n",
    "\n",
    "Whenever the overlay is downloaded, the required clocks will also be configured.\n",
    "\n",
    "References:\n",
    "\n",
    "https://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "try {\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n",
       "} catch (e) {};\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "try {\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%pybind11/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n",
       "} catch (e) {};\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pynq.overlays.base import BaseOverlay\n",
    "\n",
    "ol = BaseOverlay(\"base.bit\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "### Show All Clocks\n",
    "\n",
    "The following example shows all the current clock rates on the board. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU:   650.000000MHz\n",
      "FCLK0: 100.000000MHz\n",
      "FCLK1: 142.857143MHz\n",
      "FCLK2: 200.000000MHz\n",
      "FCLK3: 100.000000MHz\n"
     ]
    }
   ],
   "source": [
    "from pynq import Clocks\n",
    "\n",
    "print(f'CPU:   {Clocks.cpu_mhz:.6f}MHz')\n",
    "print(f'FCLK0: {Clocks.fclk0_mhz:.6f}MHz')\n",
    "print(f'FCLK1: {Clocks.fclk1_mhz:.6f}MHz')\n",
    "print(f'FCLK2: {Clocks.fclk2_mhz:.6f}MHz')\n",
    "print(f'FCLK3: {Clocks.fclk3_mhz:.6f}MHz')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set Clock Rates\n",
    "The easiest way is to set the attributes directly. Random clock rates are used in the following examples; the clock manager will set the clock rates with best effort.\n",
    "\n",
    "If the desired frequency and the closest possible clock rate differs more than 1%, a warning will be raised."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU:   650.000000MHz\n",
      "FCLK0: 27.027027MHz\n",
      "FCLK1: 31.250000MHz\n",
      "FCLK2: 14.492754MHz\n",
      "FCLK3: 0.251953MHz\n"
     ]
    }
   ],
   "source": [
    "Clocks.fclk0_mhz = 27.123456\n",
    "Clocks.fclk1_mhz = 31.436546\n",
    "Clocks.fclk2_mhz = 14.597643\n",
    "Clocks.fclk3_mhz = 0.251954\n",
    "\n",
    "print(f'CPU:   {Clocks.cpu_mhz:.6f}MHz')\n",
    "print(f'FCLK0: {Clocks.fclk0_mhz:.6f}MHz')\n",
    "print(f'FCLK1: {Clocks.fclk1_mhz:.6f}MHz')\n",
    "print(f'FCLK2: {Clocks.fclk2_mhz:.6f}MHz')\n",
    "print(f'FCLK3: {Clocks.fclk3_mhz:.6f}MHz')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reset Clock Rates\n",
    "Recover the original clock rates. This can be done by simply reloading the overlay."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FCLK0: 100.000000MHz\n",
      "FCLK1: 142.857143MHz\n",
      "FCLK2: 200.000000MHz\n",
      "FCLK3: 100.000000MHz\n"
     ]
    }
   ],
   "source": [
    "ol.download()\n",
    "\n",
    "print(f'FCLK0: {Clocks.fclk0_mhz:.6f}MHz')\n",
    "print(f'FCLK1: {Clocks.fclk1_mhz:.6f}MHz')\n",
    "print(f'FCLK2: {Clocks.fclk2_mhz:.6f}MHz')\n",
    "print(f'FCLK3: {Clocks.fclk3_mhz:.6f}MHz')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
